C++Primer 第Ⅰ部分读书笔记
变量与基本类型
extern的使用
声明而不定义
extern int i;//声明而未定义
int j;//声明并定义
在全部文件中使用const量
extern const int size = 0;
指针和const
const int * p1 = &i;//指向常量的指针
int*const p2 = &i;//指向i的常量指针
const int *const p3 = &i;//指向常量的常量指针
constexpr (C++11)
constexpr int j = 0;//显式告诉编译器这是个常量
constexpr int * p4 = &i;//指向i的常量指针
类型别名
typedef
typedef double wages;
using (C++11)
using wages = double;
别名与指针引起的误会
typedef int* wages;//类型别名声明
const wages p1 = 0;//常量指针,而非指向const的指针
decltype类型 (C++11)
decltype的基本使用
int a = 0,*b=&a,&c=a;
decltype(a) x;//返回int类型
decltype(b) y;//返回int指针类型
decltype(c) z;//错误,返回引用类型必须初始化
decltype和引用
int a = 0,*b=&a;
decltype(*b) c;//错误,*b返回类型为引用
decltype((a)) d;//返回引用int类型,但未初始化,错误
int a = 0,*b=&a,&c=a;
decltype(a) x;//返回int类型
decltype(b) y;//返回int指针类型
decltype(c) z;//错误,返回引用类型必须初始化
头文件保护符
#ifndef STRING_H//判断是否定义变量,若定义返回真,执行直到遇到 #endif
#define STRING_H //把一个名字设定为预处理变量
//源代码
#endif
类型转换
显式强制转换
基本格式:
cast-name<type>(expression);
static_cast
内层不包括const,即可使用 static_cast
找回void*指针的值
void*p1 = &d;
double *p2 = static_cast<double*>(p);
const_cast
只能改变底层const的类型转换,去掉const性质
const int val = 21;//赋值
const int*p1 = &val;//p1指向val
int*p2 = const_cast<int*>(p1);//强制类型转换
*p2 = 7;//改变值,但该行为是未定义的
不能通过p2改变val的值,该行为是未定义的
那么const_cast的作用是什么? 一个函数如果需要非常量作为参数,并且我们明确函数不会修改该值,那么我们可以通过类型转换传递参数达到目的
const_cast从来不是为了修改常量而设计的
reinterpret_cast
这里不细讲,待补充
旧式类型强制转换
typename(expr);//函数形式的强制转换
(typename)expr;//C语言风格的强制转换
函数
含有种类可变形参的函数
void fun(initializer_list<int>num);
initiallizer_list可提供多种与容器相同的方法
比如begin(),size(),size()
这样便可以传递多个形参
主函数main()的返回值
为了返回值不随机器改变而改变,应该使用cstdlib头文件中的两个预处理变量
#include<cstdlib>
int main()
{
if(some_faliure)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
返回数组指针
int (*fun(int val) ) [10]; //表示返回一个指向十个元素的数组的指针
使用尾置返回类型
auto fun(int i ) -> int(*)[10];
*必须用括号括上,原因如下
int *p1[10];// 表示一个含有十个指针的数组
int(*p)[10];//表示一个指向十个元素数组的指针
using
using Arrt = int [10];
Arrt fun(int i );
constexpr函数 (C++11)
constexpr fun(){return 42;)
constexpr int i = fun();
使用constexpr函数需要遵循返回类型为字面值类型,并且函数内只能有一句return语句
除此之外,constexpr函数返回的不一定是常量,当形参为常量表达式时,函数返回常量
否则,返回非常量
调试帮助
assert预处理宏
assert定义再 cassert头文件中
assert(exp);
若exp为真,则继续执行,若exp为假,则终止程序进行
NDEBUG预处理变量
#define NDEBUG
若定义了NDEBUG,则assert什么也不做
_
func
*定义存放函数
*
FILE
*定义存放文件
*
LINE
*定义行数
*
TIME
*定义编译时间
*
DATE
_定义编译日期
函数指针
函数指针的基本使用
bool fun(int i);
bool (*p)(int i );
p = fun;
p = &fun; //两种方式等价
int i = p(4);
int j = (*p)(4);//两种方式等价
与普通指针类似,函数指针需要声明并且不能指向不同类型
返回指向函数的指针
int (*p(int i) ) (int i);
using p = int (*q) (int i );
p fun(int i );
类
默认构造函数 =defalut (C++11)
class MAP
{
MAP() =default;//若类中有别的构造函数,但没有默认构造函数,则需要自己提供一个
}
委托构造函数 (C++11)
class Data
{
public:
Data(int Val,int Key) : val(Val),key(Key) {}
Data(int Val): Data(Val,0) {}
}
explicit构造函数
class Data{
public:
explicit Data(int Val):val(Val) {} //只能用于直接初始化,并且不能隐式转换
聚合类
1.所有成员为pubilc
2.没有类内初始值
3.没有构造函数
4.没有基类也没有虚方法
struct Data
{
string s;
int val;
}
Data temp = {"s",2);//可直接花括号初始化
静态成员
在类中声明静态成员,在类外定义并初始化静态成员
与函数类似,值得注意的是,如果是数据类型,也必须给予类型
class MAP
{
static int a;
}
int a = 5;
也可以这样初始化
class MAP
{
static constexpr int a = 5;
}
静态成员可以用来声明不完全类型
class MAP
{
public:
//...
priviate:
static MAP a;//但不能直接声明
MAP* b;